package xuan.utils.bazi;

import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;
import xuan.utils.CommonUtil;
import xuan.utils.DateUtil;

import java.util.*;

/**
 * 八字-工具
 *
 * @author 善待
 */
public class BaZiUtil {

    /**
     * 判断日期类型设置，返回公历日期、农历日期
     *
     * @param setting 八字-设置
     * @return 公历日期、农历日期
     */
    public static Map<String, Object> isDateType(BaZiSetting setting) {

        Solar solar;
        Lunar lunar;

        // 1、获取设置数据
        Date date = setting.getDate(); // 日期
        int dateType = setting.getDateType(); // 日期类型

        // 2、判断日期类型
        if (dateType == 0) {
            // 2.1、按公历日期计算
            solar = new Solar(date); // 公历日期
            lunar = solar.getLunar(); // 农历日期
        } else {
            // 2.2、按农历日期计算
            try {
                lunar = new Lunar(date.getYear() + 1900, setting.getLeapMonth() == 0 ? (date.getMonth() + 1) : -(date.getMonth() + 1), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); // 农历日期
                solar = lunar.getSolar(); // 公历日期
                System.out.println(lunar);
                System.out.println(solar);
            } catch (IllegalArgumentException e) {
                lunar = new Lunar(); // 当前农历日期
                solar = lunar.getSolar(); // 当前公历日期
//                throw new SystemException(ResponseResultEnum.DATE_ERROR); // 该日期无法排盘
            }
        }

        // 3、添加日期并返回
        Map<String, Object> map = new HashMap<>();
        map.put("solar", solar); // 公历日期
        map.put("lunar", lunar); // 农历日期
        map.put("solarStr", DateUtil.getSolarStr(solar)); // 公历日期
        map.put("lunarStr", DateUtil.getLunarStr2(lunar)); // 农历日期
        map.put("solarDate", DateUtil.stringToDate(DateUtil.getSolarStr(solar))); // 公历日期
        map.put("lunarDate", DateUtil.stringToDate(DateUtil.getLunarStr(lunar))); // 农历日期
        return map;

    }

    /**
     * 判断干支设置，返回干支
     *
     * @param setting 八字-设置
     * @param lunar   农历日期
     * @return 干支
     */
    public static Map<String, List<String>> isGanZhi(BaZiSetting setting, Lunar lunar) {

        List<String> list;
        Map<String, List<String>> map = new HashMap<>();

        // 1、判断年干支设置
        if (setting.getYearGanZhiSet() == 0) {
            list = Arrays.asList(lunar.getYearGan(), lunar.getYearZhi(), lunar.getYearInGanZhi()); // 以正月初一作为新年的开始
        } else if (setting.getYearGanZhiSet() == 1) {
            list = Arrays.asList(lunar.getYearGanByLiChun(), lunar.getYearZhiByLiChun(), lunar.getYearInGanZhiByLiChun()); // 以立春当天作为新年的开始
        } else {
            list = Arrays.asList(lunar.getYearGanExact(), lunar.getYearZhiExact(), lunar.getYearInGanZhiExact()); // 以立春交接的时刻作为新年的开始
        }
        map.put("yearGanZhi", list);

        // 2、判断月干支设置
        if (setting.getMonthGanZhiSet() == 0) {
            list = Arrays.asList(lunar.getMonthGan(), lunar.getMonthZhi(), lunar.getMonthInGanZhi()); // 以节交接当天起算
        } else {
            list = Arrays.asList(lunar.getMonthGanExact(), lunar.getMonthZhiExact(), lunar.getMonthInGanZhiExact()); // 以节交接时刻起算
        }
        map.put("monthGanZhi", list);

        // 3、判断日干支设置
        if (setting.getDayGanZhiSet() == 0) {
            list = Arrays.asList(lunar.getDayGanExact(), lunar.getDayZhiExact(), lunar.getDayInGanZhiExact()); // 晚子时日干支算明天
        } else {
            list = Arrays.asList(lunar.getDayGanExact2(), lunar.getDayZhiExact2(), lunar.getDayInGanZhiExact2()); // 晚子时日干支算当天
        }
        map.put("dayGanZhi", list);

        // 4、支持早子时和晚子时
        map.put("hourGanZhi", Arrays.asList(lunar.getTimeGan(), lunar.getTimeZhi(), lunar.getTimeInGanZhi()));

        // 5、返回干支
        return map;

    }

    /**
     * 计算天干留意
     *
     * @param yearGan    年干
     * @param monthGan   月干
     * @param dayGan     日干
     * @param hourGan    时干
     * @param daYunGan   大运干\胎元干
     * @param liuNianGan 流年干\胎息干\小运干
     * @param liuYueGan  流月干\命宫干
     * @param liuRiGan   流日干\身宫干
     * @param liuShiGan  流时干
     */
    public static List<String> tanGanLiuYi(String yearGan, String monthGan, String dayGan, String hourGan, String daYunGan, String liuNianGan, String liuYueGan, String liuRiGan, String liuShiGan) {

        Set<String> set = new HashSet<>();
        addGanZhiLiuYi(yearGan, monthGan, dayGan, hourGan, daYunGan, liuNianGan, liuYueGan, liuRiGan, liuShiGan, set, BaZiMap.TIAN_GAN_XIANG_SHENG);
        addGanZhiLiuYi(yearGan, monthGan, dayGan, hourGan, daYunGan, liuNianGan, liuYueGan, liuRiGan, liuShiGan, set, BaZiMap.TIAN_GAN_XIANG_HE);
        addGanZhiLiuYi(yearGan, monthGan, dayGan, hourGan, daYunGan, liuNianGan, liuYueGan, liuRiGan, liuShiGan, set, BaZiMap.TIAN_GAN_XIANG_CHONG);
        addGanZhiLiuYi(yearGan, monthGan, dayGan, hourGan, daYunGan, liuNianGan, liuYueGan, liuRiGan, liuShiGan, set, BaZiMap.TIAN_GAN_XIANG_KE);
        return CommonUtil.removeDuplicates(new ArrayList<>(set));

    }

    /**
     * 计算地支留意
     *
     * @param yearZhi    年支
     * @param monthZhi   月支
     * @param dayZhi     日支
     * @param hourZhi    时支
     * @param daYunZhi   大运支\胎元支
     * @param liuNianZhi 流年支\胎息支\小运支
     * @param liuYueZhi  流月支\命宫支
     * @param liuRiZhi   流日支\身宫支
     * @param liuShiZhi  流时支
     */
    public static List<String> diZhiLiuYi(String yearZhi, String monthZhi, String dayZhi, String hourZhi, String daYunZhi, String liuNianZhi, String liuYueZhi, String liuRiZhi, String liuShiZhi) {

        Set<String> set = new HashSet<>();
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_BAN_HE);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_GONG_HE);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_AN_HE);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_LIU_HE);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_XIANG_XING);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_XIANG_CHONG);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_XIANG_PO);
        addGanZhiLiuYi(yearZhi, monthZhi, dayZhi, hourZhi, daYunZhi, liuNianZhi, liuYueZhi, liuRiZhi, liuShiZhi, set, BaZiMap.DI_ZHI_XIANG_HAI);
        return CommonUtil.removeDuplicates(new ArrayList<>(set));

    }

//----------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 添加天干\地支留意
     *
     * @param yearGanZhi    年干\年支
     * @param monthGanZhi   月干\月支
     * @param dayGanZhi     日干\日支
     * @param hourGanZhi    时干\时支
     * @param daYunGanZhi   大运干\胎元干，大运支\胎元支
     * @param liuNianGanZhi 流年干\胎息干\小运干，流年支\胎息支\小运支
     * @param liuYueGanZhi  流月干\命宫干，流月支\命宫支
     * @param liuRiGanZhi   流日干\身宫干，流日支\身宫支
     * @param liuShiGanZhi  流时干。流时支
     * @param set           天干\地支组合
     * @param map           天干\地支关系
     */
    private static void addGanZhiLiuYi(String yearGanZhi, String monthGanZhi, String dayGanZhi, String hourGanZhi, String daYunGanZhi, String liuNianGanZhi, String liuYueGanZhi, String liuRiGanZhi, String liuShiGanZhi, Set<String> set, Map<String, String> map) {

        set.add(map.get(yearGanZhi + monthGanZhi));
        set.add(map.get(yearGanZhi + dayGanZhi));
        set.add(map.get(yearGanZhi + hourGanZhi));
        set.add(map.get(yearGanZhi + daYunGanZhi));
        set.add(map.get(yearGanZhi + liuNianGanZhi));
        set.add(map.get(yearGanZhi + liuYueGanZhi));
        set.add(map.get(yearGanZhi + liuRiGanZhi));
        set.add(map.get(yearGanZhi + liuShiGanZhi));

        set.add(map.get(monthGanZhi + yearGanZhi));
        set.add(map.get(monthGanZhi + dayGanZhi));
        set.add(map.get(monthGanZhi + hourGanZhi));
        set.add(map.get(monthGanZhi + daYunGanZhi));
        set.add(map.get(monthGanZhi + liuNianGanZhi));
        set.add(map.get(monthGanZhi + liuYueGanZhi));
        set.add(map.get(monthGanZhi + liuRiGanZhi));
        set.add(map.get(monthGanZhi + liuShiGanZhi));

        set.add(map.get(dayGanZhi + yearGanZhi));
        set.add(map.get(dayGanZhi + monthGanZhi));
        set.add(map.get(dayGanZhi + hourGanZhi));
        set.add(map.get(dayGanZhi + daYunGanZhi));
        set.add(map.get(dayGanZhi + liuNianGanZhi));
        set.add(map.get(dayGanZhi + liuYueGanZhi));
        set.add(map.get(dayGanZhi + liuRiGanZhi));
        set.add(map.get(dayGanZhi + liuShiGanZhi));

        set.add(map.get(hourGanZhi + yearGanZhi));
        set.add(map.get(hourGanZhi + monthGanZhi));
        set.add(map.get(hourGanZhi + dayGanZhi));
        set.add(map.get(hourGanZhi + daYunGanZhi));
        set.add(map.get(hourGanZhi + liuNianGanZhi));
        set.add(map.get(hourGanZhi + liuYueGanZhi));
        set.add(map.get(hourGanZhi + liuRiGanZhi));
        set.add(map.get(hourGanZhi + liuShiGanZhi));

        set.add(map.get(daYunGanZhi + yearGanZhi));
        set.add(map.get(daYunGanZhi + monthGanZhi));
        set.add(map.get(daYunGanZhi + dayGanZhi));
        set.add(map.get(daYunGanZhi + hourGanZhi));
        set.add(map.get(daYunGanZhi + liuNianGanZhi));
        set.add(map.get(daYunGanZhi + liuYueGanZhi));
        set.add(map.get(daYunGanZhi + liuRiGanZhi));
        set.add(map.get(daYunGanZhi + liuShiGanZhi));

        set.add(map.get(liuNianGanZhi + yearGanZhi));
        set.add(map.get(liuNianGanZhi + monthGanZhi));
        set.add(map.get(liuNianGanZhi + dayGanZhi));
        set.add(map.get(liuNianGanZhi + hourGanZhi));
        set.add(map.get(liuNianGanZhi + daYunGanZhi));
        set.add(map.get(liuNianGanZhi + liuYueGanZhi));
        set.add(map.get(liuNianGanZhi + liuRiGanZhi));
        set.add(map.get(liuNianGanZhi + liuShiGanZhi));

        set.add(map.get(liuYueGanZhi + yearGanZhi));
        set.add(map.get(liuYueGanZhi + monthGanZhi));
        set.add(map.get(liuYueGanZhi + dayGanZhi));
        set.add(map.get(liuYueGanZhi + hourGanZhi));
        set.add(map.get(liuYueGanZhi + daYunGanZhi));
        set.add(map.get(liuYueGanZhi + liuNianGanZhi));
        set.add(map.get(liuYueGanZhi + liuRiGanZhi));
        set.add(map.get(liuYueGanZhi + liuShiGanZhi));

        set.add(map.get(liuRiGanZhi + yearGanZhi));
        set.add(map.get(liuRiGanZhi + monthGanZhi));
        set.add(map.get(liuRiGanZhi + dayGanZhi));
        set.add(map.get(liuRiGanZhi + hourGanZhi));
        set.add(map.get(liuRiGanZhi + daYunGanZhi));
        set.add(map.get(liuRiGanZhi + liuNianGanZhi));
        set.add(map.get(liuRiGanZhi + liuYueGanZhi));
        set.add(map.get(liuRiGanZhi + liuShiGanZhi));

        set.add(map.get(liuShiGanZhi + yearGanZhi));
        set.add(map.get(liuShiGanZhi + monthGanZhi));
        set.add(map.get(liuShiGanZhi + dayGanZhi));
        set.add(map.get(liuShiGanZhi + hourGanZhi));
        set.add(map.get(liuShiGanZhi + daYunGanZhi));
        set.add(map.get(liuShiGanZhi + liuNianGanZhi));
        set.add(map.get(liuShiGanZhi + liuYueGanZhi));
        set.add(map.get(liuShiGanZhi + liuRiGanZhi));

    }


}
